01 de marzo de 2018
Es una colección de paquetes de R diseñados para la ciencia de datos que facilitan la manipulación, exploración y visualización de datos.
Todos los paquetes comparten una filosofía de diseño, gramática y estructuras de datos.
La mayoría de los paquetes fueron originalmente diseñados por Hadley Wickham pero ahora hay muchos contribuidores.
Entorno accesible para el análisis de datos.
tidyverseEstá diseñado para facilitar la instalación y la carga de varios paquetes en un solo comando.
# install.packages("tidyverse")
library("tidyverse")
## ── Attaching packages ───────────────────────────────────────────────────────────────────────────────────── tidyverse 1.2.1 ──
## ✔ ggplot2 2.2.1 ✔ purrr 0.2.4 ## ✔ tibble 1.4.2 ✔ dplyr 0.7.4 ## ✔ tidyr 0.8.0 ✔ stringr 1.2.0 ## ✔ readr 1.1.1 ✔ forcats 0.2.0
## ── Conflicts ──────────────────────────────────────────────────────────────────────────────────────── tidyverse_conflicts() ── ## ✖ dplyr::filter() masks stats::filter() ## ✖ dplyr::lag() masks stats::lag()
magrittr
El objetivo de usar pipes es hacer el desarrollo de código más fácil de escribir, mas rápido de leer y más sencillo de dar mantenimiento.
%>%Funciona con el operador forward pipe %>% que envía un valor a una función.
La función básica puede verse de la siguiente forma:
x %>% f equivale a f(x).x %>% f(y) equivale a f(x, y).x %>% f %>% g %>% h equivale a h(g(f(x))).Colocación de valores en argumentos por posición se realiza con un punto .:
x %>% f(y, .) equivale a f(y, x).x %>% f(y, z = .) equivale a f(y, z = x)Shortcut
El shortcut de forward pipe `%>%` es command/ctrl + shift + m
library(nycflights13) foo1 <- filter(flights, carrier == "UA") foo2 <- arrange(foo1, desc(dep_time)) head(foo2, 3)
## # A tibble: 3 x 19 ## year month day dep_time sched_dep_time dep_delay arr_time ## <int> <int> <int> <int> <int> <dbl> <int> ## 1 2013 4 18 2358 2048 190 340 ## 2 2013 3 24 2357 2151 126 44 ## 3 2013 4 10 2357 1935 262 148 ## # ... with 12 more variables: sched_arr_time <int>, arr_delay <dbl>, ## # carrier <chr>, flight <int>, tailnum <chr>, origin <chr>, dest <chr>, ## # air_time <dbl>, distance <dbl>, hour <dbl>, minute <dbl>, ## # time_hour <dttm>
flights %>% filter(carrier == "UA") %>% arrange(desc(dep_time)) %>% head(3)
## # A tibble: 3 x 19 ## year month day dep_time sched_dep_time dep_delay arr_time ## <int> <int> <int> <int> <int> <dbl> <int> ## 1 2013 4 18 2358 2048 190 340 ## 2 2013 3 24 2357 2151 126 44 ## 3 2013 4 10 2357 1935 262 148 ## # ... with 12 more variables: sched_arr_time <int>, arr_delay <dbl>, ## # carrier <chr>, flight <int>, tailnum <chr>, origin <chr>, dest <chr>, ## # air_time <dbl>, distance <dbl>, hour <dbl>, minute <dbl>, ## # time_hour <dttm>
El arte de tener los datos en R en una forma útil para la visualización y modelado
df_ejercicio <- read_csv("data/datos_ejercicio.csv")
## Parsed with column specification: ## cols( ## ent_mun = col_character(), ## indicador = col_character(), ## `2015` = col_double(), ## `2016` = col_character() ## )
df_ejercicio
## # A tibble: 24,561 x 4 ## ent_mun indicador `2015` `2016` ## <chr> <chr> <dbl> <chr> ## 1 09014 analfabeta 0.560 <NA> ## 2 15020 analfabeta 0.970 <NA> ## 3 19006 analfabeta 1.11 <NA> ## 4 09016 analfabeta 1.21 <NA> ## 5 19046 analfabeta 1.23 <NA> ## 6 20350 analfabeta 1.25 <NA> ## 7 26019 analfabeta 1.29 <NA> ## 8 26024 analfabeta 1.35 <NA> ## 9 08019 analfabeta 1.38 <NA> ## 10 15024 analfabeta 1.43 <NA> ## # ... with 24,551 more rows
filter() y arrange()# Filtrar y ordenar
df_fo <- df_ejercicio %>%
filter(indicador %in% c("analfabeta", "sin_primaria", "poblacion")) %>%
arrange(ent_mun, indicador)%>%
mutate(est = str_sub(ent_mun, start = 1, end = 2),
mun = str_sub(ent_mun, start = 3, end = 5)) %>%
select(-ent_mun)
df_fo
## # A tibble: 7,369 x 5 ## indicador `2015` `2016` est mun ## <chr> <dbl> <chr> <chr> <chr> ## 1 analfabeta 2.59 <NA> 01 001 ## 2 poblacion 870274 881300 01 001 ## 3 sin_primaria 11.5 <NA> 01 001 ## 4 analfabeta 5.54 <NA> 01 002 ## 5 poblacion 49608 50260 01 002 ## 6 sin_primaria 26.0 <NA> 01 002 ## 7 analfabeta 6.19 <NA> 01 003 ## 8 poblacion 57951 58585 01 003 ## 9 sin_primaria 28.9 <NA> 01 003 ## 10 analfabeta 4.35 <NA> 01 004 ## # ... with 7,359 more rows
gather() y spread()df_gather <- df_fo %>%
gather(key = year,
value = valor,
c(`2015`, `2016`))
df_gather
## # A tibble: 14,738 x 5 ## indicador est mun year valor ## <chr> <chr> <chr> <chr> <chr> ## 1 analfabeta 01 001 2015 2.59 ## 2 poblacion 01 001 2015 870274 ## 3 sin_primaria 01 001 2015 11.48 ## 4 analfabeta 01 002 2015 5.54 ## 5 poblacion 01 002 2015 49608 ## 6 sin_primaria 01 002 2015 26.02 ## 7 analfabeta 01 003 2015 6.19 ## 8 poblacion 01 003 2015 57951 ## 9 sin_primaria 01 003 2015 28.88 ## 10 analfabeta 01 004 2015 4.35 ## # ... with 14,728 more rows
gather() y spread()df_tidy <- df_gather %>%
spread(key = indicador,
value = valor)
df_tidy
## # A tibble: 4,914 x 6 ## est mun year analfabeta poblacion sin_primaria ## <chr> <chr> <chr> <chr> <chr> <chr> ## 1 01 001 2015 2.59 870274 11.48 ## 2 01 001 2016 <NA> 881300 <NA> ## 3 01 002 2015 5.54 49608 26.02 ## 4 01 002 2016 <NA> 50260 <NA> ## 5 01 003 2015 6.19 57951 28.88 ## 6 01 003 2016 <NA> 58585 <NA> ## 7 01 004 2015 4.35 16274 21.81 ## 8 01 004 2016 <NA> 16483 <NA> ## 9 01 005 2015 3.76 112342 18.21 ## 10 01 005 2016 <NA> 114130 <NA> ## # ... with 4,904 more rows
Mirar los datos, generar hipótesis rápidamente, probarlas rápidamente y luego repetirlas una y otra vez. Generar muchas pistas.
group_by(), mutate() y summarise()
df_resumen <- df_tidy %>%
# ordenar para obtener diferencia poblacional
arrange(est, mun, year) %>%
# tidyverse verbs
mutate_at(.vars = c('analfabeta', 'poblacion', 'sin_primaria'),
.funs = parse_number) %>%
# agrupar por estado y municipio
group_by(est, mun) %>%
# diferencia de poblacion de 2015 a 2016
mutate(analfabeta = mean(analfabeta, na.rm = T),
sin_primaria = mean(sin_primaria, na.rm = T),
dif_poblacion = diff(poblacion),
difp_poblacion = dif_poblacion/poblacion) %>%
# desagrupar
ungroup %>%
# únicamente cambio porcentual de 2016
filter(year == '2016')
df_resumen
## # A tibble: 2,457 x 8 ## est mun year analfabeta poblacion sin_primaria dif_poblacion ## <chr> <chr> <chr> <dbl> <dbl> <dbl> <dbl> ## 1 01 001 2016 2.59 881300 11.5 11026 ## 2 01 002 2016 5.54 50260 26.0 652 ## 3 01 003 2016 6.19 58585 28.9 634 ## 4 01 004 2016 4.35 16483 21.8 209 ## 5 01 005 2016 3.76 114130 18.2 1788 ## 6 01 006 2016 4.11 45463 18.7 555 ## 7 01 007 2016 4.70 53560 19.2 665 ## 8 01 008 2016 3.45 9320 18.9 124 ## 9 01 009 2016 5.91 21843 26.8 291 ## 10 01 010 2016 5.77 20626 25.7 254 ## # ... with 2,447 more rows, and 1 more variable: difp_poblacion <dbl>
"Una gráfica simple ha traído más información a la mente del analista de datos que cualquier otro recurso." - John Tukey
ggplot2Es una sistema para crear gráficos basado en la gramática de gráficos con los mismos elementos.
Se basa en el trabajo de Wilkinson y propone la gramática en capas o layered grammar of graphics adaptado a R.
La gramática nos dice que un gráfico estadístico es un mapeo de datos a atributos estéticos de objetos geométricos en sistemas de coordenadas específicos.
Existen tres componentes básicos en ggplot2:
data: Dataframe de datos a graficar.aes aesthetic mappings: Mapeo de las variables del conjunto de datos y la propiedades visuales a valores estéticos de la gráfica.geoms: Al menos una capa con objetos geométricos que describan como tratar cada observación.df_resumen %>%
filter(est %in% c("07", "09", "28", "30")) %>%
ggplot(aes(x = analfabeta, y = sin_primaria,
color = est)) +
geom_point(alpha = .5, size = 2)
df_resumen %>%
filter(est %in% c("07", "09", "28", "30")) %>%
ggplot(aes(x = analfabeta, y = difp_poblacion,
color = est)) +
geom_point(alpha = .5, size = 2)
df_resumen %>%
filter(est %in% c("07", "09", "28", "30")) %>%
# recodificación de factores
mutate(est = forcats::fct_recode(est,
chiapas = '07',
cdmx = '09',
tamaulipas = '28',
veracruz = '30')) %>%
ggplot(aes(x = sin_primaria, y = difp_poblacion,
color = est)) +
geom_point(alpha = .5, size = 2) +
# etiquetas
ylab("Diferencia porcentual\npoblación") +
xlab("Porc. sin primaria") +
ggtitle("Relación de variables.",
"Información por municipio.") +
guides(color = guide_legend(title = "Entidad"))
mod_1 <- lm(formula = difp_poblacion ~ sin_primaria, data = df_resumen) summary(mod_1)
## ## Call: ## lm(formula = difp_poblacion ~ sin_primaria, data = df_resumen) ## ## Residuals: ## Min 1Q Median 3Q Max ## -0.0210081 -0.0028225 -0.0002315 0.0027997 0.0227699 ## ## Coefficients: ## Estimate Std. Error t value Pr(>|t|) ## (Intercept) 1.355e-02 3.016e-04 44.94 <2e-16 *** ## sin_primaria -1.397e-04 8.814e-06 -15.85 <2e-16 *** ## --- ## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 ## ## Residual standard error: 0.004688 on 1891 degrees of freedom ## (564 observations deleted due to missingness) ## Multiple R-squared: 0.1172, Adjusted R-squared: 0.1168 ## F-statistic: 251.2 on 1 and 1891 DF, p-value: < 2.2e-16
broomConvierte en data frames ordenados la salida desordenada de las funciones incorporadas en R, como lm, nls o t.test.
library(broom) tidy(mod_1)
## term estimate std.error statistic p.value ## 1 (Intercept) 0.013554178 3.015929e-04 44.94197 1.080268e-300 ## 2 sin_primaria -0.000139689 8.814329e-06 -15.84794 3.305014e-53
modelrProporciona funciones que ayudan a crear pipelines elegantes al modelar.
library(modelr) tab_results <- df_resumen %>% # agrega una columna de predicciones modelr::add_predictions(model = mod_1) %>% # agrega una columna de residuales modelr::add_residuals(model = mod_1)
## est mun year analfabeta poblacion sin_primaria dif_poblacion ## 1 01 001 2016 2.59 881300 11.48 11026 ## 2 01 002 2016 5.54 50260 26.02 652 ## 3 01 003 2016 6.19 58585 28.88 634 ## 4 01 004 2016 4.35 16483 21.81 209 ## 5 01 005 2016 3.76 114130 18.21 1788 ## 6 01 006 2016 4.11 45463 18.74 555 ## difp_poblacion pred resid ## 1 0.01251106 0.011950549 0.0005605146 ## 2 0.01297254 0.009919471 0.0030530718 ## 3 0.01082188 0.009519961 0.0013019222 ## 4 0.01267973 0.010507562 0.0021721691 ## 5 0.01566635 0.011010442 0.0046559036 ## 6 0.01220773 0.010936407 0.0012713227
do()# Un poco mas complicado
modelo_fun <- function(sub_tab){
mod <- lm(formula = difp_poblacion ~ sin_primaria, data = sub_tab)
broom::tidy(mod)
}
tbl_modelos <- df_resumen %>%
# divido en subgrupos por estado
group_by(est) %>%
# aplicar la función para cada subgrupo
do(modelo_fun(sub_tab = .))
## # A tibble: 8 x 6 ## # Groups: est [4] ## est term estimate std.error statistic p.value ## <chr> <chr> <dbl> <dbl> <dbl> <dbl> ## 1 01 (Intercept) 0.0151 0.00236 6.39 0.000127 ## 2 01 sin_primaria -0.0000887 0.000107 -0.826 0.430 ## 3 02 (Intercept) 0.0112 0.00578 1.94 0.147 ## 4 02 sin_primaria 0.000231 0.000396 0.583 0.601 ## 5 03 (Intercept) 0.0358 0.00754 4.74 0.0178 ## 6 03 sin_primaria -0.000482 0.000419 -1.15 0.333 ## 7 04 (Intercept) 0.0134 0.00301 4.47 0.00156 ## 8 04 sin_primaria 0.0000171 0.000104 0.165 0.873
library(ggrepel) tbl_modelos %>% select(est:estimate) %>% spread(term, estimate) %>% ggplot(aes(x = `(Intercept)`, y = sin_primaria)) + geom_text_repel(aes( label = est)) + geom_point()
modelo_fun2 <- function(sub_tab){
mod <- lm(formula = difp_poblacion ~ sin_primaria, data = sub_tab)
}
tbl_modelos_2 <- df_resumen %>%
group_by(est) %>%
do(modelo = modelo_fun2(sub_tab = .),
#guardar el modelo
coefs = broom::tidy(x = modelo_fun2(sub_tab = .)),
# coeficientes en dataframe
rmse = modelr::rmse(model = modelo_fun2(sub_tab = .),
data = .) )
# calcula rmse
tbl_modelos_2 %>% head
## # A tibble: 6 x 4 ## est modelo coefs rmse ## <chr> <list> <list> <list> ## 1 01 <S3: lm> <data.frame [2 × 5]> <dbl [1]> ## 2 02 <S3: lm> <data.frame [2 × 5]> <dbl [1]> ## 3 03 <S3: lm> <data.frame [2 × 5]> <dbl [1]> ## 4 04 <S3: lm> <data.frame [2 × 5]> <dbl [1]> ## 5 05 <S3: lm> <data.frame [2 × 5]> <dbl [1]> ## 6 06 <S3: lm> <data.frame [2 × 5]> <dbl [1]>
http://r4ds.had.co.nz/introduction.html
tidyverseVideo: https://www.rstudio.com/resources/videos/data-science-in-the-tidyverse/
Cursos gratis: https://www.tidyverse.org/learn/#datacamp
Algunos libros: https://www.tidyverse.org/learn/#books
Cheat sheets: https://www.rstudio.com/resources/cheatsheets/
Más cheat sheets: https://s3.amazonaws.com/assets.datacamp.com/blog_assets/Tidyverse+Cheat+Sheet.pdf
CRAN: https://cran.r-project.org/web/packages/tidyverse/index.html
Los verbos básicos: https://github.com/animalito/tidyverse-verbs
Github: https://github.com/Songeo/intro_tidyverse_2018.git
github: Songeo
email: sonia.gmcl@gmail.com